package com.xyoto.community.webSocketServer;

import com.alibaba.fastjson.JSON;
import com.xyoto.community.aspect.annotation.RequiresLogin;
import com.xyoto.community.constant.ReadStatus;
import com.xyoto.community.mapper.main.MessageMapper;
import com.xyoto.community.pojo.TransmissionEntity;
import com.xyoto.community.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author coderFu
 * @create 2022/2/19
 * webSocket 服务类 webSocket 的 连接，客户端信息的接收，连接的中断等
 */
@Component
@ServerEndpoint(value = "/webSocket/{userId}")
@Slf4j
public class WebSocketServer {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);


    private static MessageMapper messageMapper;



    @Autowired
    public void setMessageMapper(MessageMapper messageMapper){
        WebSocketServer.messageMapper = messageMapper;
    }

    /**
     * 前端发送的心跳内容
     */
    private static final String HEART_MESSAGE = "ping";


    /**
     * 与客户端的会话信息
     */
    private Session session;

    /**
     * 客户端的唯一标识
     */
    private Integer userId;


    private static  Map<Integer, WebSocketServer> clients = new ConcurrentHashMap<Integer,WebSocketServer>();


    @OnOpen
    public void onOpen(@PathParam("userId") Integer userId, Session session){
        this.session = session;
        this.userId = userId;
        logger.info("用户："+userId+",成功连接到后台");
        // 将会话存储到Map集合中
        clients.put(userId,this);
        //查询是否有未读消息存在并发送消息给前端
        currentMessageStatus(session,userId);
    }

    @OnClose
    public void onClose(){
        logger.info("用户："+userId+",退出后台");
        clients.remove(userId);
    }

    /**
     * 处理前端发来的信息，在这里处理心跳机制
     */
    @OnMessage
    public void onMessage(String message,Session session){
        // 构造传输对象
        TransmissionEntity transmissionEntity = new TransmissionEntity();
        transmissionEntity.setHeartReply("pang");
        // 接收前端发来的心跳 ping，并返回 pang
        if (HEART_MESSAGE.equals(message)){
            // 调用方法回复心跳信息 “pang”
            sendMessageToOne(transmissionEntity,session);
        }
    }

    /**
     * 错误情况处理
     */
    @OnError
    public void onError(Session session, Throwable error){
        logger.info("当前连接发生错误："+userId);
        error.printStackTrace();
    }


    /**
     * 给指定客户端发布消息
     * @param message
     * @param session
     */
    public void sendMessageToOne(TransmissionEntity message, Session session){
        try {
            session.getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (IOException e) {
            logger.info("向用户"+userId+"信息发送失败");
            e.printStackTrace();
        }
    }

    /**
     * 查询当前是否有未读消息存在
     * @param session
     * @param userId
     */
    public void currentMessageStatus(Session session, Integer userId){
        // 根据用户id 查询是否有未读消息存在
        Integer count = messageMapper.checkIsExistNewestMessage(userId, ReadStatus.UNREAD);

        // 构造传输对象
        TransmissionEntity transmissionEntity = new TransmissionEntity();

        if (count != null && count >0){
            transmissionEntity.setStatus(1);
        }else {
            transmissionEntity.setStatus(2);
        }
        sendMessageToOne(transmissionEntity,session);
    }

    /**
     * 向指定用户推送消息
     * @param message
     * @param userId
     */
    public void sendMessageToUser(TransmissionEntity message, Integer userId){

        // 获取会话信息
        WebSocketServer webSocketServer = clients.get(userId);
        if (webSocketServer != null){
            try {
                if (message == null){
                    message = new TransmissionEntity();
                    message.setStatus(1);
                }
                webSocketServer.session.getBasicRemote().sendText(JSON.toJSONString(message));
            } catch (IOException e) {
                logger.info("向用户"+userId+",发送信息失败");
                e.printStackTrace();
            }
        }
    }


    /**
     * 简单模拟群发消息
     * @param message
     */
    public void sendMessageToAll(TransmissionEntity message){
        for (WebSocketServer webSocketServer : clients.values()){
            try {
                webSocketServer.session.getBasicRemote().sendText(JSON.toJSONString(message));
            } catch (IOException e) {
                logger.info("对用户:"+webSocketServer.userId+",发生信息失败");
                e.printStackTrace();
            }
        }
    }














}
